package com.ruoyi.driver.service.impl;

import com.ruoyi.driver.mapper.DriverUserMapper;
import com.ruoyi.driver.domain.DriverUser;
import com.ruoyi.driver.domain.FaceRecognitionResult;
import com.ruoyi.driver.service.IFaceRecognitionResultService;
import com.ruoyi.driver.domain.Drivers;
import com.ruoyi.driver.service.IDriversService;
import com.ruoyi.driver.service.FaceRecognitionService;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import okhttp3.*;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 人脸识别服务类
 * 实现百度云API的人脸识别功能
 */
@Service
public class FaceRecognitionServiceImpl implements FaceRecognitionService {
    
    // 百度云API配置
    @Value("${baidu.api.apiKey}")
    private String apiKey;
    
    @Value("${baidu.api.secretKey}")
    private String secretKey;
    
    // 百度云API URL
    private static final String AUTH_URL = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s";
    private static final String FACE_DETECT_URL = "https://aip.baidubce.com/rest/2.0/face/v3/detect";
    private static final String FACE_SEARCH_URL = "https://aip.baidubce.com/rest/2.0/face/v3/search";
    
    // 百度云人脸库组ID
    private static final String FACE_GROUP_ID = "user";
    
    // OkHttpClient实例
    private final OkHttpClient client;
    
    // 缓存的百度云API Token
    private String cachedAccessToken;
    private long tokenExpirationTime;
    
    // 日志记录器
    private static final Logger log = LoggerFactory.getLogger(FaceRecognitionServiceImpl.class);
    
    @Autowired
    private DriverUserMapper driverUserMapper;
    
    @Autowired
    private IFaceRecognitionResultService faceRecognitionResultService;
    
    @Autowired
    private IDriversService driversService;
    
    public FaceRecognitionServiceImpl() {
        // 初始化OkHttpClient，设置连接超时时间为30秒
        this.client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();
        
        // 初始化缓存Token相关变量
        this.cachedAccessToken = null;
        this.tokenExpirationTime = 0;
    }
    
    @Override
    public String getAuthToken() {
        // 检查缓存的Token是否有效（提前5分钟刷新）
        if (cachedAccessToken != null && System.currentTimeMillis() < tokenExpirationTime - 5 * 60 * 1000) {
            log.info("使用缓存的百度云API Token");
            return cachedAccessToken;
        }
        
        String url = String.format(AUTH_URL, apiKey, secretKey);
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        try {
            log.info("开始获取百度云API Token，请求URL: {}", url);
            Response response = client.newCall(request).execute();
            if (response.body() != null) {
                String result = response.body().string();
                log.info("获取百度云API Token响应: {}, 状态码: {}", result, response.code());
                
                if (response.isSuccessful()) {
                    JSONObject jsonObject = new JSONObject(result);
                    // 检查是否包含access_token字段
                    if (jsonObject.has("access_token")) {
                        String token = jsonObject.getString("access_token");
                        int expiresIn = jsonObject.optInt("expires_in", 0);
                        
                        // 更新缓存的Token和过期时间
                        this.cachedAccessToken = token;
                        this.tokenExpirationTime = System.currentTimeMillis() + (expiresIn * 1000L);
                        
                        log.info("成功获取百度云API Token，有效期: {}秒，将在{}后过期", 
                                expiresIn, tokenExpirationTime - System.currentTimeMillis());
                        return token;
                    } else {
                        log.error("百度云API Token响应不包含access_token字段: {}", result);
                        return null;
                    }
                } else {
                    log.error("获取百度云API Token失败: 状态码={}, 响应={}", response.code(), result);
                    return null;
                }
            } else {
                log.error("获取百度云API Token失败: 响应体为空，状态码: {}", response.code());
                return null;
            }
        } catch (Exception e) {
            log.error("获取百度云API Token异常", e);
            return null;
        }
    }
    
    @Override
    public Map<String, Object> faceRegister(String imageBase64, String userId, String userName) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            // 先检测人脸的质量
            JSONObject detectResult = faceDetect(imageBase64);
            if (detectResult.has("error")) {
                resultMap.put("success", false);
                resultMap.put("message", detectResult.getString("error"));
                return resultMap;
            }

            // 检查是否检测到人脸
            if (!detectResult.has("error_code") || detectResult.getInt("error_code") != 0) {
                resultMap.put("success", false);
                resultMap.put("message", "人脸检测失败: " + detectResult.optString("error_msg", "未知错误"));
                return resultMap;
            }

            JSONObject result = detectResult.getJSONObject("result");
            int faceNum = result.optInt("face_num", 0);

            if (faceNum < 1) {
                resultMap.put("success", false);
                resultMap.put("message", "未检测到人脸");
                return resultMap;
            }

            // 调用百度云人脸注册API，将人脸注册到人脸库中
            JSONObject registerResult = doFaceRegister(imageBase64, userId, userName);
            if (registerResult.has("error")) {
                resultMap.put("success", false);
                resultMap.put("message", registerResult.getString("error"));
                return resultMap;
            }

            // 检查注册结果
            if (!registerResult.has("error_code") || registerResult.getInt("error_code") != 0) {
                resultMap.put("success", false);
                resultMap.put("message", "人脸注册失败: " + registerResult.optString("error_msg", "未知错误"));
                return resultMap;
            }

            // 注册成功
            resultMap.put("success", true);
            resultMap.put("message", "人脸注册成功");
            resultMap.put("faceToken", registerResult.getJSONObject("result").getString("face_token"));
            
            return resultMap;
        } catch (Exception e) {
            log.error("人脸注册异常", e);
            resultMap.put("success", false);
            resultMap.put("message", "注册异常: " + e.getMessage());
            return resultMap;
        }
    }
    
    /**
     * 人脸注册方法
     * 将人脸注册到百度云人脸库
     * @param imageBase64 人脸图片Base64编码
     * @param userId 用户ID
     * @param userName 用户名
     * @return 注册结果JSON
     */
    private JSONObject doFaceRegister(String imageBase64, String userId, String userName) {
        try {
            // 百度云人脸注册API URL
            String FACE_REGISTER_URL = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add";
            
            String accessToken = getAuthToken();
            if (accessToken == null) {
                return new JSONObject().put("error", "获取Token失败");
            }
            
            String url = FACE_REGISTER_URL + "?access_token=" + accessToken;
            
            JSONObject requestBody = new JSONObject();
            requestBody.put("image", imageBase64);
            requestBody.put("image_type", "BASE64");
            requestBody.put("group_id", FACE_GROUP_ID);
            requestBody.put("user_id", userId);
            requestBody.put("user_info", userName);
            requestBody.put("quality_control", "NORMAL");
            requestBody.put("liveness_control", "LOW");
            
            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(requestBody.toString(), MediaType.parse("application/json; charset=utf-8")))
                    .build();
            
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                log.info("百度云人脸注册响应: {}", result);
                return new JSONObject(result);
            } else {
                log.error("百度云人脸注册失败: 状态码={}", response.code());
                return new JSONObject().put("error", "人脸注册请求失败");
            }
        } catch (Exception e) {
            log.error("人脸注册异常", e);
            return new JSONObject().put("error", "人脸注册异常: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> recognizeFace(String imageBase64) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            // 先检测人脸的质量
            JSONObject detectResult = faceDetect(imageBase64);
            if (detectResult.has("error")) {
                resultMap.put("success", false);
                resultMap.put("message", detectResult.getString("error"));
                return resultMap;
            }

            // 检查是否检测到人脸
            if (!detectResult.has("error_code") || detectResult.getInt("error_code") != 0) {
                resultMap.put("success", false);
                resultMap.put("message", "人脸检测失败: " + detectResult.optString("error_msg", "未知错误"));
                return resultMap;
            }

            JSONObject result = detectResult.getJSONObject("result");
            int faceNum = result.optInt("face_num", 0);

            if (faceNum < 1) {
                resultMap.put("success", false);
                resultMap.put("message", "未检测到人脸");
                return resultMap;
            }

            // 调用百度云人脸搜索API，在人脸库中搜索匹配的人脸
            JSONObject searchResult = faceSearch(imageBase64);
            // 添加日志记录完整的搜索结果结构
            log.info("百度云人脸搜索完整结果: {}", searchResult.toString());
            if (searchResult.has("error")) {
                resultMap.put("success", false);
                resultMap.put("message", searchResult.getString("error"));
                return resultMap;
            }

            // 检查搜索结果
            if (!searchResult.has("error_code") || searchResult.getInt("error_code") != 0) {
                resultMap.put("success", false);
                resultMap.put("message", "人脸搜索失败: " + searchResult.optString("error_msg", "未知错误"));
                return resultMap;
            }

            // 获取搜索结果中的匹配信息
            JSONObject searchData = searchResult.getJSONObject("result");
            JSONArray userList = searchData.optJSONArray("user_list");
            if (userList == null || userList.length() == 0) {
                resultMap.put("success", false);
                resultMap.put("message", "未匹配到司机信息");
                return resultMap;
            }

            // 获取匹配度最高的用户
            JSONObject bestMatch = userList.getJSONObject(0);
            double score = bestMatch.optDouble("score", 0);
            String userId = bestMatch.optString("user_id", "");
            
            // 从百度云API的响应结果中，face_token在searchResult的result对象中
            String faceToken = searchData.optString("face_token", "");
            
            // 增加详细日志记录，便于调试
            log.info("从百度云API获取到的face_token: {}, searchData完整内容: {}", faceToken, searchData.toString());
            
            // 验证face_token是否正确获取
            if (faceToken.isEmpty()) {
                log.warn("获取到的face_token为空，这可能导致无法查询到司机信息");
            }

            // 设置识别成功信息
            resultMap.put("success", true);
            resultMap.put("message", "人脸识别成功");
            resultMap.put("quality", result.optJSONObject("face_list"));
            
            // 根据faceToken从数据库中查询司机信息
            log.info("开始根据face_token查询司机信息: {}", faceToken);
            DriverUser driverUser = driverUserMapper.selectDriverUserByFaceToken(faceToken);
            log.info("司机信息查询结果: {}", (driverUser == null ? "未找到司机" : "找到司机，ID: " + driverUser.getId()));
            
            // 如果face_token查询失败，尝试获取身份证号码作为备选方案
            if (driverUser == null) {
                // 从百度云API响应中获取用户信息
                String userInfo = bestMatch.optString("user_info", "");
                log.info("face_token查询失败，百度云API返回的用户信息: {}", userInfo);
                
                // 在实际应用中，这里应该有一个机制来根据用户信息获取身份证号码
                // 由于没有直接的映射关系，这里我们假设存在一个方法可以根据用户信息获取身份证号码
                // 注意：这只是一个示例实现，实际实现需要根据项目的具体情况来定
                String idCard = getUserInfoToIdCard(userInfo);
                
                if (!idCard.isEmpty()) {
                    log.info("获取到的身份证号码: {}", idCard);
                    driverUser = driverUserMapper.selectDriverUserByIdCard(idCard);
                    log.info("使用身份证号码查询司机信息结果: {}", (driverUser == null ? "未找到司机" : "找到司机，ID: " + driverUser.getId()));
                } else {
                    log.warn("无法根据用户信息获取身份证号码");
                }
            }
            
            if (driverUser != null) {
                // 构建返回的用户信息
                Map<String, Object> userInfo = new HashMap<>();
                userInfo.put("driverId", driverUser.getId());
                userInfo.put("driverName", driverUser.getDriverName());
                userInfo.put("driverPhone", getDriverPhoneById(driverUser.getId())); // 需要实现此方法获取司机手机号
                userInfo.put("licenseNumber", getDriverLicenseNumberById(driverUser.getId())); // 需要实现此方法获取车牌号
                userInfo.put("matchScore", score);
                userInfo.put("recognitionTime", new Date());
                
                resultMap.put("userInfo", userInfo);
                
                // 保存识别结果到数据库
                saveRecognitionResult(driverUser.getId(), imageBase64, resultMap);
            } else {
                resultMap.put("success", false);
                resultMap.put("message", "未找到匹配的司机信息");
            }
            
            return resultMap;
        } catch (Exception e) {
            log.error("人脸识别异常", e);
            resultMap.put("success", false);
            resultMap.put("message", "识别异常: " + e.getMessage());
            return resultMap;
        }
    }
    
    /**
     * 人脸检测方法
     * 用于检测图片中的人脸是否清晰、是否符合要求
     * @param imageBase64 人脸图片Base64编码
     * @return 检测结果JSON
     */
    @Override
    public JSONObject faceDetect(String imageBase64) {
        try {
            String accessToken = getAuthToken();
            if (accessToken == null) {
                return new JSONObject().put("error", "获取Token失败");
            }
            
            String url = FACE_DETECT_URL + "?access_token=" + accessToken;
            
            JSONObject requestBody = new JSONObject();
            requestBody.put("image", imageBase64);
            requestBody.put("image_type", "BASE64");
            
            // 设置检测选项
            JSONObject options = new JSONObject();
            options.put("face_field", "age,beauty,expression,face_shape,gender,glasses,landmark,race,quality,facetype");
            options.put("max_face_num", 1);
            requestBody.put("options", options);
            
            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(requestBody.toString(), MediaType.parse("application/json; charset=utf-8")))
                    .build();
            
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                return new JSONObject(result);
            } else {
                return new JSONObject().put("error", "请求失败");
            }
        } catch (Exception e) {
            log.error("人脸检测异常", e);
            return new JSONObject().put("error", "检测异常");
        }
    }
    
    /**
     * 人脸搜索方法
     * 在百度云人脸库中搜索匹配的人脸
     * @param imageBase64 人脸图片Base64编码
     * @return 搜索结果JSON
     */
    private JSONObject faceSearch(String imageBase64) {
        try {
            String accessToken = getAuthToken();
            if (accessToken == null) {
                return new JSONObject().put("error", "获取Token失败");
            }
            
            String url = FACE_SEARCH_URL + "?access_token=" + accessToken;
            
            JSONObject requestBody = new JSONObject();
            requestBody.put("image", imageBase64);
            requestBody.put("image_type", "BASE64");
            requestBody.put("group_id_list", FACE_GROUP_ID);
            requestBody.put("quality_control", "NORMAL");
            requestBody.put("liveness_control", "LOW");
            
            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(requestBody.toString(), MediaType.parse("application/json; charset=utf-8")))
                    .build();
            
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                log.info("百度云人脸搜索响应: {}", result);
                return new JSONObject(result);
            } else {
                log.error("百度云人脸搜索失败: 状态码={}", response.code());
                return new JSONObject().put("error", "人脸搜索请求失败");
            }
        } catch (Exception e) {
            log.error("人脸搜索异常", e);
            return new JSONObject().put("error", "人脸搜索异常: " + e.getMessage());
        }
    }
    
    /**
     * 根据用户信息（姓名）获取身份证号码
     * 通过查询数据库获取真实的司机身份证信息
     */
    private String getUserInfoToIdCard(String userInfo) {
        try {
            if (userInfo == null || userInfo.isEmpty()) {
                log.warn("用户信息为空，无法获取身份证号码");
                return "";
            }
            
            // 通过driverUserMapper查询数据库，根据用户信息（姓名）获取司机信息
            log.info("开始根据用户信息查询司机身份证号码: {}", userInfo);
            
            // 创建查询条件
            DriverUser queryDriver = new DriverUser();
            queryDriver.setDriverName(userInfo);
            
            // 查询司机信息
            List<DriverUser> driverList = driverUserMapper.selectDriverUserList(queryDriver);
            log.info("根据姓名查询到的司机数量: {}", driverList.size());
            
            // 如果查询到司机信息，返回第一个匹配的司机的身份证号码
            if (driverList != null && !driverList.isEmpty()) {
                DriverUser driverUser = driverList.get(0);
                String idCard = driverUser.getIdCard();
                log.info("查询到的司机身份证号码: {}", idCard);
                return idCard != null ? idCard : "";
            } else {
                log.warn("未找到姓名为 '{}' 的司机信息", userInfo);
                return "";
            }
        } catch (Exception e) {
            log.error("根据用户信息获取身份证号码异常", e);
            return "";
        }
    }
    
    /**
     * 根据司机ID获取司机手机号
     */
    private String getDriverPhoneById(Long driverId) {
        try {
            Drivers driver = driversService.selectDriversById(driverId);
            if (driver != null && driver.getPhoneNumber() != null) {
                return driver.getPhoneNumber();
            }
            log.warn("司机[{}]的手机号未找到", driverId);
            return "";
        } catch (Exception e) {
            log.error("获取司机手机号异常", e);
            return "";
        }
    }
    
    /**
     * 根据司机ID获取车牌号
     * 注意：当前项目中未找到直接关联司机和车辆的表结构
     * 实际应用中需要根据具体的数据模型和业务需求实现
     */
    private String getDriverLicenseNumberById(Long driverId) {
        // 这里应该从数据库中查询车牌号
        // 由于当前项目未找到司机与车辆的关联关系，暂时返回一个示例车牌号
        log.warn("当前项目中未找到司机与车辆的关联关系，返回示例车牌号");
        return "京A12345";
    }
    
    /**
     * 保存人脸识别结果到数据库
     */
    private void saveRecognitionResult(Long driverId, String imageBase64, Map<String, Object> recognitionInfo) {
        try {
            FaceRecognitionResult result = new FaceRecognitionResult();
            result.setDriverId(driverId);
            result.setImageBase64(imageBase64);
            
            // 从识别信息中提取匹配分数
            if (recognitionInfo.containsKey("userInfo")) {
                Map<String, Object> userInfo = (Map<String, Object>) recognitionInfo.get("userInfo");
                if (userInfo.containsKey("matchScore")) {
                    result.setMatchScore(Double.valueOf(userInfo.get("matchScore").toString()));
                }
            }
            
            // 设置识别状态(0成功 1失败)
            boolean success = (boolean) recognitionInfo.getOrDefault("success", false);
            result.setStatus(success ? 0 : 1);
            
            // 保存完整的识别结果JSON
            String resultJson = new JSONObject(recognitionInfo).toString();
            result.setResultJson(resultJson);
            
            // 调用service保存到数据库
            faceRecognitionResultService.insertFaceRecognitionResult(result);
            log.info("成功保存司机[{}]的人脸识别结果", driverId);
        } catch (Exception e) {
            log.error("保存人脸识别结果失败", e);
            // 注意：这里不抛出异常，避免影响主流程
        }
    }
}
